"""
@Author：WangYuXiang
@E-mile：Hill@3io.cc
@CreateTime：2021/4/13 17:30
@DependencyLibrary：无
@MainFunction：无
@FileDoc： 
    role.py
    文件说明
@ChangeHistory:
    datetime action why
    example:
    2021/4/13 17:30 change 'Fix bug'
        
"""

from common.auth.models import RoleModel, UserModel
from common.auth.serializers import RoleModelSerializer, RoleEmployUserListSerializer, RoleDimsissSerializer, RoleEmployUserSerializer
from common.utils.authentication import GeneralTokenAuthenticate
from sanic_rest_framework import mixins
from sanic_rest_framework.exceptions import APIException
from sanic_rest_framework.paginations import ORMPagination
from sanic_rest_framework.status import HttpStatus
from sanic_rest_framework.views import ModelViewSet, GeneralView, ViewSetView


class RoleViewSet(ModelViewSet):
    queryset = RoleModel
    serializer_class = RoleModelSerializer
    search_fields = ('@code',)
    authentication_classes = (GeneralTokenAuthenticate,)

    async def list(self, request, *args, **kwargs):
        queryset = await self.get_queryset()
        serializer = self.get_serializer(queryset, many=True)
        data = await serializer.data
        return self.success_json_response(data=data)


class RoleEmployUserListView(mixins.RetrieveModelMixin, ViewSetView):
    """角色下聘任的用户列表"""
    search_fields = ('@account', '@nickname')
    authentication_classes = (GeneralTokenAuthenticate,)
    serializer_class = RoleEmployUserListSerializer
    queryset = UserModel
    pagination_class = ORMPagination

    async def get_queryset(self):
        pk = self.kwargs.get('pk')
        queryset = self.queryset.filter(roles__pk=pk).filter(await self.filter_orm()).prefetch_related('roles')
        return queryset

    async def retrieve(self, request, *args, **kwargs):
        queryset = await self.get_queryset()
        page = await self.paginate_queryset(queryset)
        self.paginator.set_count(await self.get_paginator_count(queryset))
        serializer = self.get_serializer(page, many=True)
        data = self.get_paginated_response(await serializer.data)
        return self.success_json_response(data=data)


class RoleDismissView(GeneralView):
    authentication_classes = (GeneralTokenAuthenticate,)

    async def get_role_object(self, pk):
        role = await RoleModel.get_or_none(pk=pk)
        if not role:
            raise APIException(message='未发现资源', http_status=HttpStatus.HTTP_404_NOT_FOUND)
        return role

    async def get_user_object(self, account):
        user = await UserModel.get_or_none(account=account)
        if not user:
            raise APIException(message='未发现资源', http_status=HttpStatus.HTTP_404_NOT_FOUND)
        return user

    async def delete(self, request, *args, **kwargs):
        serializer = RoleDimsissSerializer(data=request.data)
        await serializer.is_valid(raise_exception=True)
        role = await self.get_role_object(serializer.validated_data.get('pk'))
        user = await self.get_user_object(serializer.validated_data.get('account'))
        await role.users.remove(user)
        return self.success_json_response()


class RoleEmployView(GeneralView):
    authentication_classes = (GeneralTokenAuthenticate,)

    async def get_role_object(self, pk):
        role = await RoleModel.get_or_none(pk=pk)
        if not role:
            raise APIException(message='未发现资源', http_status=HttpStatus.HTTP_404_NOT_FOUND)
        return role

    async def get_user_object(self, pk):
        user = await UserModel.get_or_none(pk=pk)
        if not user:
            raise APIException(message='未发现资源', http_status=HttpStatus.HTTP_404_NOT_FOUND)
        return user

    async def post(self, request, *args, **kwargs):
        serializer = RoleEmployUserSerializer(data=request.data)
        await serializer.is_valid(raise_exception=True)
        user_id = serializer.validated_data.get('user_id')
        role_id = serializer.validated_data.get('role_id')
        role = await self.get_role_object(role_id)
        user = await self.get_user_object(user_id)
        await role.users.add(user)
        data = await RoleEmployUserListSerializer(instance=user).data
        return self.success_json_response(data=data)
